/**
 *Copyright (c) 2024 watereyes
 * safetymanagement is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan
 * PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *          http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */
package com.koron.web.servlet;

import com.alibaba.fastjson.JSON;
import com.google.gson.Gson;
import com.koron.common.StaffAttribute;
import com.koron.common.Tools;
import com.koron.common.bean.*;
import com.koron.common.dfs.FastDFSClientWrapper;
import com.koron.common.domain.CurrentUserInfo;
import com.koron.common.permission.SPIAccountAnno;
import com.koron.common.stub.Port;
import com.koron.common.web.Util;
import com.koron.hazardsource.util.BusinessCode;
import com.koron.personal.domain.MyCertificate;
import com.koron.personal.mapper.MyCertificateMapper;
import com.koron.purpose.bean.JobsStaffBean;
import com.koron.purpose.mapper.JobsStaffMapper;
import com.koron.risk.bean.CorpBean;
import com.koron.risk.service.api.CorpManagementService;
import com.koron.system.service.api.LogService;
import com.koron.system.util.ServletUtils;
import com.koron.util.Constant;
import com.koron.util.VerifyCodeBean;
import com.koron.web.staff.mapper.PasswordMapper;
import com.koron.web.staff.mapper.StaffMapper;
import com.koron.web.vo.LoginBean;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.koron.ebs.mybatis.ADOConnection;
import org.koron.ebs.mybatis.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import org.swan.bean.MessageBean;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;

@Api(tags = "casLoginAction", description = "单点登录接口")
@RestController
@EnableScheduling
public class CASLoginAction {

    private final static  Logger logger = LoggerFactory.getLogger(CASLoginAction.class);

    @Value("${app.appid:}")
    private String appid;

    @Value("${app.secret:}")
    private String secret;

    @Value("${login.callback:}")
    private String callback;

    @Autowired
    private CorpManagementService corpService;

    @Autowired
    private LogService logService;

    @Autowired
    private Util util;

    public  volatile static  Map<String, String> UserTokenMap = new HashMap<>();

    private Map<String, LoginBean> AccountMap = new HashMap<>();

    // 用来缓存验证码
    public volatile static Map<String, VerifyCodeBean> VerifyCode = new HashMap<>();

    /**
     * 定时任务清除缓存
     * 每分钟执行一次
     */
    @Scheduled(cron = "0  */1 * * * ?")
    public void executeCronJobClearVerifyCode() {
        if (!VerifyCode.isEmpty()) {
            Map<String, VerifyCodeBean> map = new HashMap<>();
            map.putAll(VerifyCode);
            Set<String> keySet = map.keySet();
            for (String uuid : keySet) {
                VerifyCodeBean bean = map.get(uuid);
                if (null != bean) {
                    if (System.currentTimeMillis() > bean.getDate()) {
                        VerifyCode.remove(uuid);
                    }
                }
            }
        }
    }

    @ApiOperation("登录接口")
    @RequestMapping("/cas.htm")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userid", value = "用户名", required = false, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "password", value = "密码", required = false, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "code", value = "企业微信登录时成员授权获取到的code", required = false, paramType = "query", dataType = "String"),
    })
    @ApiIgnore
    public String login(@SPIAccountAnno @StaffAttribute("verify_code") @ApiIgnore String uuid,HttpServletRequest request, HttpServletResponse response) {
        try (SessionFactory factory = new SessionFactory()) {
            MessageBean<String> msg = new MessageBean<>();
            String userid = request.getParameter("userid");
            String password = request.getParameter("password");
            String verify = request.getParameter("verify");
            //账号密码登录
            //校验验证码
            if (AccountMap.containsKey(userid)) {
                LoginBean login = AccountMap.get(userid);
                Integer count = login.getCount();
                if (count >= 3){
                    // 账号密码错误三次后，需要输入验证码
                    if (StringUtils.isEmpty(uuid)) {
                        uuid = (String) request.getSession().getAttribute("verify_code");
                    }
                    VerifyCodeBean bean = VerifyCode.get(uuid);
                    VerifyCode.remove(uuid);
                    if (null == bean || System.currentTimeMillis() > bean.getDate()) {
                        msg.setCode(30013);
                        msg.setDescription("验证码已失效");
                        return msg.toJson();
                    }
                    if (StringUtils.isEmpty(verify) || !verify.equalsIgnoreCase(bean.getCode())) {
                        msg.setCode(30013);
                        msg.setDescription("验证码输入错误");
                        return msg.toJson();
                    }
                }
            }
            if (StringUtils.isEmpty(userid) || StringUtils.isEmpty(password)) {
                msg.setCode(1100);
                msg.setDescription("用户名或密码为空");
                return msg.toJson();
            }
            com.koron.web.staff.bean.StaffBean staffBean = factory.getMapper(StaffMapper.class).getStaffById(userid);
            if (null == staffBean) {
                msg.setCode(1101);
                msg.setDescription("用户名或密码错误");
                return msg.toJson();
            } else {
                if (staffBean.getStatus() == 1) {
                    msg.setCode(1101);
                    msg.setDescription("用户已停用");
                    return msg.toJson();
                }
                // 验证账号密码是否正确
                if (1 != factory.getMapper(PasswordMapper.class).auth(userid, password)) {
                    Integer count = 1;
                    if (AccountMap.containsKey(userid)) {
                        LoginBean login = AccountMap.get(userid);
                        count = login.getCount();
                        count++;
                        login.setCount(count);
                        if (count >= 3) {
                            long time = System.currentTimeMillis() / 1000 + 300;
                            login.setTime(time);
                            AccountMap.put(userid, login);
                            msg.setCode(30013);
                            msg.setDescription("用户名或密码错误");
                            return msg.toJson();
                        }
                        AccountMap.put(userid, login);
                    } else {
                        LoginBean login = new LoginBean();
                        login.setCount(count);
                        AccountMap.put(userid, login);
                    }
                    msg.setCode(1101);
                    msg.setDescription("用户名或密码错误");
                    return msg.toJson();
                } else {
                    // 登录成功移除登录限制
                    if (AccountMap.containsKey(userid)) {
                        AccountMap.remove(userid);
                    }
                    if ("825a758a78842553b735bb22335e5d0e".equals(password) || ("7918fe079303c541ce31aa58f5c7b7e0").equals(password)) {
                        msg.setCode(30012);
                        msg.setDescription("请修改密码");
                        return msg.toJson();
                    }
                    StaffBean staffBean1 = new StaffBean();
                    BeanUtils.copyProperties(staffBean, staffBean1);
                    //获取用户所在部门
                    List<DeptBean> deptBeanList = (List<DeptBean>) util.dept(staffBean.getCode()).getData();
                    if (null != deptBeanList) {
                        staffBean1.setDepartmentCode(deptBeanList.get(0).getCode());
                        staffBean1.setDepartmentname(deptBeanList.get(0).getName());
                        staffBean1.setDepartmentid(deptBeanList.get(0).getId());
                    }
                    request.getSession().setAttribute("_user", staffBean1);
                    msg.setCode(Constant.MESSAGE_INT_SUCCESS);
                    msg.setDescription("登录成功");
                    String token = Tools.getCode32();
                    msg.setData(token);
                    UserTokenMap.put(token, staffBean1.getUserid());
                    return msg.toJson();
                }
            }
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            logger.error(e.getMessage(),e);
            MessageBean<String> msg = new MessageBean<>();
            msg.setCode(1102);
            msg.setDescription("登录异常");
            return msg.toJson();
        }
    }

    @RequestMapping("/nouser.htm")
    public String nouser() {
        return "用户名或密码错误!";
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @ApiOperation(value = "获取用户及操作列表")
    @ApiImplicitParam(name = "ticket", value = "登录标识", required = true, paramType = "query", dataType = "String")
    @RequestMapping(value = "/getOperations.htm", method = {RequestMethod.GET})
    public String getOperations(@SPIAccountAnno @StaffAttribute("_user") @ApiIgnore StaffBean user) {
        StaffBean self = ServletUtils.getSigninUser();
        if (self == null && user != null) {
            ServletUtils.getSession().setAttribute("_user", user);
        }
        // 记录到登录日志,单独try{}catch异常,登录日志记录成功与否，不影响功能
        try {
            logService.signinLog();
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
        }
        MessageBean<Map> msg = MessageBean.create(BusinessCode.MESSAGE_CODE_SUCCESS, BusinessCode.MESSAGE_DESCRIPTION_SUCCESS, Map.class);
        if (user == null) {
            msg.setCode(BusinessCode.MESSAGE_CODE_ACTION_EXCEPTION);
            msg.setDescription(BusinessCode.MESSAGE_DESCRIPTION_ACTION_EXCEPTION);
            return msg.toJson();
        }
        try {
            SecretBean secretBean = new SecretBean();
            secretBean.setAppid(appid);
            secretBean.setSecret(secret);
            Port port = new Port(secretBean);
            long seq = 0;
            msg = port.getOperations(seq, 2, -1, -1, user.getCode());
            Map map = msg.getData();
            if (map == null) {
                map = new HashMap();
            }
            if (map.get("list") == null) {
                map.put("list", new ArrayList());
            }
            map.put("user", user);
            return msg.toJson();
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            msg.setCode(BusinessCode.MESSAGE_CODE_ACTION_EXCEPTION);
            msg.setDescription(BusinessCode.MESSAGE_DESCRIPTION_ACTION_EXCEPTION);
            return msg.toJson();
        }
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    @ApiOperation(value = "获取用户的权限公司")
    @ApiImplicitParam(name = "ticket", value = "登录标识", required = true, paramType = "query", dataType = "String")
    @RequestMapping(value = "/getOperationCorp.htm", method = {RequestMethod.GET})
    public String getOperationCorp(@SPIAccountAnno @StaffAttribute("_user") @ApiIgnore StaffBean user) {
        MessageBean<List> msg = new MessageBean();
        if (user == null) {
            msg.setCode(BusinessCode.MESSAGE_CODE_ACTION_EXCEPTION);
            msg.setDescription(BusinessCode.MESSAGE_DESCRIPTION_ACTION_EXCEPTION);
            return msg.toJson();
        }
        try {
            //已开通的公司列表
            List<CorpBean> corpBeanList = corpService.corpBeanList();
            if (corpBeanList == null) {
                return msg.toJson();
            }
            Map<String, CorpBean> corpMap = corpBeanList.stream().collect(Collectors.toMap(CorpBean::getCorpCode, corp -> corp, (v1, v2) -> v2));

            LinkedHashSet<String> codeSet = new LinkedHashSet<String>();
            //是否放入默认公司

            SecretBean secretBean = new SecretBean();
            secretBean.setAppid(appid);
            secretBean.setSecret(secret);
            Port port = new Port(secretBean);
            //获取群组列表
            MessageBean<Map> groupMap = port.getRolesAndGroupsByStaff(user.getCode(), 512);
            Map map = groupMap.getData();
            if (map != null) {
                List<GroupBean> groutList = (List<GroupBean>) map.get("group");
                if (groutList != null) {
                    List<String> attrList = groutList.stream().map(GroupBean::getAttr).collect(Collectors.toList());
                    //从群组的attr属性中取出已分配的corpCode
                    for (String attr : attrList) {
                        Map<String, String> attrMap = (Map<String, String>) JSON.parse(attr);
                        if (attrMap != null) {
                            String corpCode = attrMap.get("corpCode");
                            if (corpCode != null) {
                                String[] codeArray = corpCode.split(",");
                                for (String str : codeArray) {
                                    codeSet.add(str);
                                }
                            }
                        }
                    }
                }
            }
            List<CorpBean> ret = new ArrayList<CorpBean>();
            for (String str : codeSet) {
                if (corpMap.keySet().contains(str)) {
                    ret.add(corpMap.get(str));
                }
            }
            if (ret.size() == 0) {
                msg.setCode(-1);
                msg.setDescription("无权限");
                return msg.toJson();
            }
            msg.setData(ret);
            return msg.toJson();
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            msg.setCode(-1);
            msg.setDescription("无权限");
            return msg.toJson();
        }
    }

    /**
     * 获取用户信息
     */
    @ApiOperation(value = "获取当前登录用户信息")
    @RequestMapping(value = "/getCurrentUserInfo.htm", method = {RequestMethod.POST})
    public MessageBean getCurrentUserInfo(@SPIAccountAnno @StaffAttribute("_user") @ApiIgnore StaffBean user) {
        MessageBean msg = MessageBean.create(BusinessCode.MESSAGE_CODE_SUCCESS, BusinessCode.MESSAGE_DESCRIPTION_SUCCESS, String.class);
        StaffBean self = ServletUtils.getSigninUser();
        if (null == user && null == self) {
            return MessageBean.create(BusinessCode.MESSAGE_CODE_ACTION_EXCEPTION, BusinessCode.MESSAGE_DESCRIPTION_ACTION_EXCEPTION, String.class);
        }
        if (self == null && user != null) {
            ServletUtils.getSession().setAttribute("_user", user);
        }
        CurrentUserInfo info = new CurrentUserInfo();
        BeanUtils.copyProperties(user, info);
        //获取用户所属部门
        List<DeptBean> deptBeanList = (List<DeptBean>) util.dept(info.getCode()).getData();
        if (null != deptBeanList) {
            info.setDepartmentCode(deptBeanList.get(0).getCode());
            info.setDepartmentName(deptBeanList.get(0).getName());
        }
        //获取人员所属公司
        DepartmentTreeBean corp = (DepartmentTreeBean) util.corp(user.getCode()).getData();
        info.setCompanyCode(corp.getDepartmentCode()); //设置人员公司code
        info.setCompanyName(corp.getName()); //设置人员公司名称
        try (SessionFactory factory = new SessionFactory();) {
            // 获取用户头像
            String photo = factory.getMapper(StaffBeanMapper.class).getPhoto(info.getCode());
            if (StringUtils.isNotEmpty(photo)) {
                info.setPhoto(photo);
            }else {
                info.setPhoto(new Gson().toJson(new ArrayList<>()));
            }
            // 获取用户岗位
            JobsStaffBean bean = factory.getMapper(JobsStaffMapper.class).queryById(info.getCode());
            if (null != bean) {
                info.setJobsId(bean.getJobsId());
                info.setJobsName(bean.getJobsName());
//                info.setJobsNote(bean.getNote());
            }
            // 获取用户证照(默认展示一个，点击查看所有)
            List<MyCertificate> list = factory.getMapper(MyCertificateMapper.class).queryByCondition(info.getCode(), 0, 1, null);
            if (null != list && list.size() > 0) {
                info.setCertificateName(list.get(0).getCertificateName());
            }
            // 获取用户常用功能开启情况
            Integer isOpenCommon = factory.getMapper(StaffBeanMapper.class).getIsOpenCommon(info.getCode());
            info.setIsOpenCommon(null != isOpenCommon && isOpenCommon == 1);
        }
        msg.setData(info);
        return msg;
    }


    @Autowired
    private FastDFSClientWrapper clientWrapper;

    /**
     * 更新用户头像
     */
    @ApiOperation(value = "更新用户头像")
    @RequestMapping(value = "/updatePhoto.htm", method = {RequestMethod.POST})
    public MessageBean updatePhoto(@SPIAccountAnno @StaffAttribute("_user") @ApiIgnore StaffBean user, @RequestParam(required = false) final MultipartFile[] files) {
        MessageBean msg = MessageBean.create(BusinessCode.MESSAGE_CODE_SUCCESS, BusinessCode.MESSAGE_DESCRIPTION_SUCCESS, String.class);
        return ADOConnection.runTask(factory -> {
            try {
                StaffBeanMapper mapper = factory.getMapper(StaffBeanMapper.class);
                List<String> keepList = new ArrayList<>();
                for (MultipartFile file : files) {
                    String url = clientWrapper.uploadFile(file);
                    keepList.add(url + "#" + file.getOriginalFilename());
                }
                String photo = new Gson().toJson(keepList);
                mapper.updatePhoto(user.getCode(), photo);
            } catch (Exception e) {
                logger.error(e.getMessage(),e);
                factory.close(false);
                msg.setCode(BusinessCode.MESSAGE_CODE_FAIL);
                msg.setDescription(BusinessCode.MESSAGE_DESCRIPTION_FAIL);
            }
            return msg;
        }, MessageBean.class);
    }

    /**
     * 更新用户常用功能设置
     */
    @ApiOperation(value = "更新用户常用功能设置")
    @RequestMapping(value = "/updateOpenCommon.htm", method = {RequestMethod.POST})
    public MessageBean updateOpenCommon(@SPIAccountAnno @StaffAttribute("_user") @ApiIgnore StaffBean user, @RequestParam(required = true) final Boolean isOpenCommon) {
        MessageBean msg = MessageBean.create(BusinessCode.MESSAGE_CODE_SUCCESS, BusinessCode.MESSAGE_DESCRIPTION_SUCCESS, String.class);
        return ADOConnection.runTask(factory -> {
            try {
                StaffBeanMapper mapper = factory.getMapper(StaffBeanMapper.class);
                mapper.updateOpenCommon(user.getCode(), isOpenCommon);
            } catch (Exception e) {
                logger.error(e.getMessage(),e);
                factory.close(false);
                msg.setCode(BusinessCode.MESSAGE_CODE_FAIL);
                msg.setDescription(BusinessCode.MESSAGE_DESCRIPTION_FAIL);
            }
            return msg;
        }, MessageBean.class);
    }

    /**
     * 获取用户信息
     */
    @ApiOperation(value = "获取token用户信息")
    @RequestMapping(value = "/getUserInfo.htm", method = {RequestMethod.POST})
    public MessageBean getUserInfo(HttpServletRequest request, HttpServletResponse response, String token) throws Exception {
        MessageBean msg = MessageBean.create(BusinessCode.MESSAGE_CODE_SUCCESS, BusinessCode.MESSAGE_DESCRIPTION_SUCCESS, String.class);
        logger.info("获取的token：" + token);
        String name = null;
        // 解析token,获取人员姓名
        if (StringUtils.isNotEmpty(token)) {
            String str = UserTokenMap.get(token);
            logger.info("token获取到的name：" + str);
            msg.setData(str);
            return msg;
        }
        return MessageBean.create(BusinessCode.MESSAGE_CODE_FAIL, BusinessCode.MESSAGE_DESCRIPTION_FAIL, String.class);
    }


    @RequestMapping("/pendingTrial.htm")
    @ApiIgnore
    public ModelAndView PendingTrial() {
        return new ModelAndView("redirect:" + callback + "?ticket=" + Tools.getCode32() + "#/taskFlowExamine/pendingTrial");
    }
    @RequestMapping("/index.htm")
    @ApiIgnore
    public ModelAndView index() {
        return new ModelAndView("redirect:" + callback);
    }

}
